package org.example.dbcompare.service;


import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.example.dbcompare.model.config.IgnoreTableConfig;

import java.util.Set;
import java.util.regex.Pattern;

/**
 * 忽略表配置服务
 * @author wuyong
 * @date 2025/10/22
 */
@Slf4j
public class IgnoreTableConfigService {

    private static final String CONFIG_FILE_NAME = "ignore_tables_config.json";

    /**
     * 保存忽略表配置
     */
    public void saveConfig(IgnoreTableConfig config) {
        try {
            String configPath = CompareUtils.getResourceDirectoryPath() + "/" + CONFIG_FILE_NAME;
            String jsonContent = JSONUtil.toJsonPrettyStr(config);
            FileUtil.writeUtf8String(jsonContent, configPath);
            log.info("忽略表配置已保存到: {}", configPath);
        } catch (Exception e) {
            log.error("保存忽略表配置时发生错误: {}", e.getMessage(), e);
        }
    }

    /**
     * 加载忽略表配置
     */
    public IgnoreTableConfig loadConfig() {
        try {
            String configPath = CompareUtils.getResourceDirectoryPath() + "/" + CONFIG_FILE_NAME;

            if (!FileUtil.exist(configPath)) {
                log.info("忽略表配置文件不存在，创建默认配置");
                return createDefaultConfig();
            }

            String jsonContent = FileUtil.readUtf8String(configPath);
            IgnoreTableConfig config = JSONUtil.toBean(jsonContent, IgnoreTableConfig.class);
            log.info("成功加载忽略表配置");
            return config;

        } catch (Exception e) {
            log.error("加载忽略表配置时发生错误: {}", e.getMessage(), e);
            return createDefaultConfig();
        }
    }

    /**
     * 创建默认配置
     */
    private IgnoreTableConfig createDefaultConfig() {
        return IgnoreTableConfig.builder()
                .description("默认忽略表配置")
                .version("1.0")
                .build();
    }

    /**
     * 检查表是否应该被完全忽略
     */
    public boolean shouldIgnoreTable(String tableName, IgnoreTableConfig config) {
        if (config == null || config.getIgnoreTables() == null) {
            return false;
        }

        // 检查精确匹配
        if (config.getIgnoreTables().contains(tableName)) {
            return true;
        }

        // 检查模式匹配
        return matchesPatterns(tableName, config.getIgnorePatterns());
    }

    /**
     * 检查表是否应该忽略结构对比
     */
    public boolean shouldIgnoreTableStructure(String tableName, IgnoreTableConfig config) {
        if (config == null) {
            return false;
        }

        // 如果完全忽略，则也忽略结构对比
        if (shouldIgnoreTable(tableName, config)) {
            return true;
        }

        // 检查结构对比忽略列表
        if (config.getIgnoreTableStructure() != null &&
                config.getIgnoreTableStructure().contains(tableName)) {
            return true;
        }

        return false;
    }

    /**
     * 检查表是否应该忽略列对比
     */
    public boolean shouldIgnoreColumnCompare(String tableName, IgnoreTableConfig config) {
        if (config == null) {
            return false;
        }

        // 如果完全忽略或忽略结构对比，则也忽略列对比
        if (shouldIgnoreTable(tableName, config) ||
                shouldIgnoreTableStructure(tableName, config)) {
            return true;
        }

        // 检查列对比忽略列表
        if (config.getIgnoreColumnCompare() != null &&
                config.getIgnoreColumnCompare().contains(tableName)) {
            return true;
        }

        return false;
    }

    /**
     * 检查表名是否匹配忽略模式
     */
    private boolean matchesPatterns(String tableName, Set<String> patterns) {
        if (patterns == null || patterns.isEmpty()) {
            return false;
        }

        for (String pattern : patterns) {
            if (matchesPattern(tableName, pattern)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查表名是否匹配单个模式
     */
    private boolean matchesPattern(String tableName, String pattern) {
        if (pattern == null || pattern.isEmpty()) {
            return false;
        }

        // 将通配符模式转换为正则表达式
        String regex = pattern.replace("*", ".*").replace("?", ".");
        return Pattern.matches(regex, tableName);
    }
}
